package com.lhb.aicodemother.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.lhb.aicodemother.constant.UserConstant;
import com.lhb.aicodemother.exception.BusinessException;
import com.lhb.aicodemother.exception.ErrorCode;
import com.lhb.aicodemother.exception.ThrowUtils;
import com.lhb.aicodemother.mapper.ChatHistoryMapper;
import com.lhb.aicodemother.model.dto.chathistory.ChatHistoryQueryRequest;
import com.lhb.aicodemother.model.entity.App;
import com.lhb.aicodemother.model.entity.ChatHistory;
import com.lhb.aicodemother.model.entity.User;
import com.lhb.aicodemother.model.enums.ChatHistoryMessageTypeEnum;
import com.lhb.aicodemother.service.AppService;
import com.lhb.aicodemother.service.ChatHistoryService;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;

import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 对话历史 服务层实现。
 *
 * @author lihai
 */
@Service
@Slf4j
public class ChatHistoryServiceImpl extends ServiceImpl<ChatHistoryMapper, ChatHistory> implements ChatHistoryService {

    @Resource
    @Lazy
    private AppService appService;

    @Override
    public boolean addChatMessage(Long appId, String message, String messageType, Long userId) {
        // 1.校验参数
        ThrowUtils.throwIf(appId == null || appId < 0, ErrorCode.PARAMS_ERROR);
        ThrowUtils.throwIf(StrUtil.isBlank(message), ErrorCode.PARAMS_ERROR);
        ThrowUtils.throwIf(userId == null || userId < 0, ErrorCode.PARAMS_ERROR);
        ThrowUtils.throwIf(StrUtil.isBlank(messageType), ErrorCode.PARAMS_ERROR);
        ChatHistoryMessageTypeEnum enumByValue = ChatHistoryMessageTypeEnum.getEnumByValue(messageType);
        ThrowUtils.throwIf(enumByValue == null, ErrorCode.PARAMS_ERROR, "不支持的消息类型：" + messageType);
        // 2.保存历史对话并返回结果
        ChatHistory chatHistory = new ChatHistory();
        chatHistory.setAppId(appId);
        chatHistory.setMessage(message);
        chatHistory.setMessageType(messageType);
        chatHistory.setUserId(userId);
        return this.save(chatHistory);
    }

    @Override
    public boolean deleteByAppId(Long appId) {
        QueryWrapper queryWrapper = QueryWrapper.create()
                .eq("appId", appId);

        return this.remove(queryWrapper);
    }

    @Override
    public QueryWrapper getQueryWrapper(ChatHistoryQueryRequest request) {
        QueryWrapper queryWrapper = QueryWrapper.create();
        // 校验
        if (request == null) {
            return queryWrapper;
        }
        // 获取查询条件
        Long id = request.getId();
        String message = request.getMessage();
        String messageType = request.getMessageType();
        Long userId = request.getUserId();
        LocalDateTime lastCreateTime = request.getLastCreateTime();
        Long appId = request.getAppId();
        String sortField = request.getSortField();
        String sortOrder = request.getSortOrder();

        // 拼接查询条件
        queryWrapper.eq("id", id)
                .like("message", message)
                .eq("messageType", messageType)
                .eq("userId", userId)
                .eq("appId", appId);

        // 设置游标查询 --使用createTime字段
        if (lastCreateTime != null) {
            queryWrapper.lt("createTime", lastCreateTime);
        }

        // 排序
        if (StrUtil.isNotBlank(sortField)) {
            queryWrapper.orderBy(sortField, "ascend".equals(sortOrder));
        } else {
            queryWrapper.orderBy("createTime", false);
        }
        return queryWrapper;
    }

    @Override
    public Page<ChatHistory> listAppChatHistoryByPage(Long appId, int pageSize, LocalDateTime lastCreateTime, User longinUser) {
        // 1.校验参数
        ThrowUtils.throwIf(appId == null || appId < 0, ErrorCode.PARAMS_ERROR);

        // 2.只有应用拥有者和管理员才能查询对话历史
        App app = appService.getById(appId);
        ThrowUtils.throwIf(app == null, ErrorCode.PARAMS_ERROR, "应用不存在");
        boolean isAdmin = longinUser.getUserRole().equals(UserConstant.ADMIN_ROLE);
        boolean isCreate = longinUser.getId().equals(app.getUserId());
        ThrowUtils.throwIf(!isAdmin && !isCreate, ErrorCode.NO_AUTH_ERROR, "无权查看该应用的历史对阿胡");

        // 3.构建查询条件，获取查询包装类
        ChatHistoryQueryRequest chatHistoryQueryRequest = new ChatHistoryQueryRequest();
        chatHistoryQueryRequest.setAppId(appId);
        chatHistoryQueryRequest.setLastCreateTime(lastCreateTime);
        QueryWrapper queryWrapper = this.getQueryWrapper(chatHistoryQueryRequest);

        // 4.分页查询
        return this.page(Page.of(1, pageSize), queryWrapper);
    }

    @Override
    public int loadChatHistoryToMemory(Long appId, MessageWindowChatMemory chatMemory, int maxCount) {
        try {
            // 1.根据appId查询数据库得到该appId的历史对话
            // 构建查询包装器
            QueryWrapper queryWrapper = QueryWrapper.create()
                    .eq("appId", appId)
                    .orderBy("createTime", false);
            List<ChatHistory> historyList = this.list(queryWrapper);
            if (CollUtil.isEmpty(historyList)) {
                return 0;
            }
            // 反转列表，保证时间顺序
            historyList = historyList.reversed();

            // 遍历之前先清除chatMemory里的缓存
            chatMemory.clear();
            // 记录加载数据到记忆中的数量
            int loadCount = 0;
            // 2.遍历列表，将历史对话分别写入对话记忆中
            for (ChatHistory chatHistory : historyList) {
                // 判断是Ai还是User
                if (chatHistory.getMessageType().equals(ChatHistoryMessageTypeEnum.AI.getValue())) {
                    chatMemory.add(AiMessage.from(chatHistory.getMessage()));
                    loadCount++;
                } else if (chatHistory.getMessageType().equals(ChatHistoryMessageTypeEnum.USER.getValue())) {
                    chatMemory.add(UserMessage.from(chatHistory.getMessage()));
                    loadCount++;
                }
            }

            // 3。返回加载的数量
            log.info("成功为appId{},加载了{}条数据", appId, loadCount);
            return loadCount;
        }catch (Exception e) {
            log.info("加载历史对话失败，appId:{},error:{}", appId, e);
            return 0;
        }
    }
}
